#include "GLTwoVAOTriangleWindow.h"

GLTwoVAOTriangleWindow::GLTwoVAOTriangleWindow(QWidget* parent)
	: QOpenGLWidget(parent)
{
	this->resize(QSize(480, 480));
	this->setWindowTitle("两个VAO管理两个三角形");
	this->setWindowIcon(QIcon("images/opencv.png"));
}
void GLTwoVAOTriangleWindow::initializeGL() {
	initializeOpenGLFunctions();
	//清屏颜色
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);

	qDebug() << "初始化成功";
	createAndLinkProgram(GL_VERTEX_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle.vert"
		, GL_FRAGMENT_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle.frag");


	float firstTriangle[] = {
		-0.9f, -0.5f, 0.0f,  // left 
		-0.0f, -0.5f, 0.0f,  // right
		-0.45f, 0.5f, 0.0f,  // top 
	};
	float secondTriangle[] = {
		0.0f, -0.5f, 0.0f,  // left
		0.9f, -0.5f, 0.0f,  // right
		0.45f, 0.5f, 0.0f   // top 
	};


	glGenBuffers(2, VBOs);
	glGenVertexArrays(2, VAOs); // we can also generate multiple VAOs or buffers at the same time
	// first triangle setup
	// --------------------
	glBindVertexArray(VAOs[0]);
	glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);	// Vertex attributes stay the same
	glEnableVertexAttribArray(0);
	// glBindVertexArray(0); // no need to unbind at all as we directly bind a different VAO the next few lines
	// second triangle setup
	// ---------------------
	glBindVertexArray(VAOs[1]);	// note that we bind to a different VAO now
	glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);	// and a different VBO
	glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); // because the vertex data is tightly packed we can also specify 0 as the vertex attribute's stride to let OpenGL figure it out
	glEnableVertexAttribArray(0);

}
void GLTwoVAOTriangleWindow::createAndLinkProgram(GLenum vertexShaderType, QString vertexResPath,
	GLenum fragmentShaderType, QString fragmentResPath) {
	//编译顶点着色器和片元着色器
	GLuint vertexShader = getShaderId(GL_VERTEX_SHADER, vertexResPath);
	GLuint fragmentShader = getShaderId(GL_FRAGMENT_SHADER, fragmentResPath);
	programId = glCreateProgram();
	glAttachShader(programId, vertexShader);
	glAttachShader(programId, fragmentShader);
	glLinkProgram(programId);
	int success;
	char infoLog[512];
	glGetProgramiv(programId, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(programId, 512, NULL, infoLog);
		qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog;
	}
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);
}
GLuint GLTwoVAOTriangleWindow::getShaderId(GLenum shaderType, QString resPath) {
	//创建顶点着色器
	unsigned int shaderId = glCreateShader(shaderType);
	QFile vertexShaderFile(resPath);
	if (!vertexShaderFile.open(QIODevice::ReadOnly)) {
		qDebug() << "Cannot open vertex shader file for reading";
	}
	QString verQStr = vertexShaderFile.readAll();
	std::string verStdStr = verQStr.toStdString();
	const char* vertexStr = verStdStr.c_str();
	qDebug() << "vertexStr-------------" << vertexStr;
	vertexShaderFile.close();
	glShaderSource(shaderId, 1, &vertexStr, NULL);
	glCompileShader(shaderId);
	int success;
	char infoLog[512];
	glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
		qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog;
	}
	return shaderId;
}
void GLTwoVAOTriangleWindow::resizeGL(int w, int h) {
	glViewport(0, 0, w, h);
}
void GLTwoVAOTriangleWindow::paintGL() {

	glUseProgram(programId);
	// draw first triangle using the data from the first VAO
	glBindVertexArray(VAOs[0]);
	glDrawArrays(GL_TRIANGLES, 0, 3);
	// then we draw the second triangle using the data from the second VAO
	glBindVertexArray(VAOs[1]);
	glDrawArrays(GL_TRIANGLES, 0, 3);
}
GLTwoVAOTriangleWindow::~GLTwoVAOTriangleWindow()
{
	
}
